package btspider_lib

import ( //必需
	"fmt"

	"github.com/henrylee2cn/pholcus/common/goquery"

	//DOM解析
	//信息输出
	"regexp"

	"github.com/henrylee2cn/pholcus/app/downloader/request"
	. "github.com/henrylee2cn/pholcus/app/spider" //必需
	"github.com/henrylee2cn/pholcus/logs"
	// . "github.com/henrylee2cn/pholcus/app/spider/common"          //选用
	// net包
	// "net/http" //设置http.Header
	// "net/url"
	// 编码包
	// "encoding/xml"
	"encoding/json"
	// 其他包
	// "math"
	// "time"

	"strings"
)

func init() {
	btaHome.Register()
}

var btaHome = &Spider{
	Name:            "autohome",
	Description:     "汽车之家报价 [http://car.autohome.com.cn/]",
	EnableCookie:    true,
	NotDefaultField: false,
	Namespace:       nil,
	SubNamespace:    nil,
	RuleTree: &RuleTree{
		Root: func(ctx *Context) {
			ctx.AddQueue(&request.Request{Url: "http://car.autohome.com.cn/AsLeftMenu/As_LeftListNew.ashx?typeId=1 &brandId=0 &fctId=0 &seriesId=0", Rule: "brand"})
			// ctx.AddQueue(&request.Request{Url: "http://car.autohome.com.cn/config/spec/30293.html#pvareaid=102170", Rule: "config"})
			// ctx.AddQueue(&request.Request{Url: "http://car.autohome.com.cn/config/spec/31516.html#pvareaid=102170", Rule: "config"})

			// logs.Log.Critical("Root")
		},
		Trunk: map[string]*Rule{
			"brand": {
				ItemFields: []string{
					"id",
					"href",
					"label",
					"num",
					"letter",
				},
				ParseFunc: func(ctx *Context) {
					str := ctx.GetText()
					reg := regexp.MustCompile(`document.writeln\(\"(?P<content>.*?)\"\)`)
					reg.ReplaceAllString(str, "${content}")

					str = reg.ReplaceAllString(str, "${content}")
					s := strings.NewReader(str)

					// br := bufio.NewReader(s)
					doc, err := goquery.NewDocumentFromReader(s)

					if nil != err {
						logs.Log.Error("err %v", err.Error())
					}

					doc.Find(".cartree-letter").Each(func(i int, letter *goquery.Selection) {
						letter.NextFilteredUntil("ul", ".cartree-letter").Each(func(j int, ul *goquery.Selection) {
							text := letter.Text()
							ul.Find("li").Each(func(k int, li *goquery.Selection) {
								if id, ok := li.Attr("id"); ok {
									if href, ok := li.Find("a").First().Attr("href"); ok {
										reg_id := regexp.MustCompile(`b(?P<id>\d+)`)
										reg_label := regexp.MustCompile(`(?P<label>.*?)\((?P<num>\d+)\)`)
										// reg_num := regexp.MustCompile(`b(?<id>\d+)`)
										label := li.Text()
										id := reg_id.ReplaceAllString(id, "${id}")
										// ctx.FileOutput("dfafaf.txt")
										ctx.Output(map[int]interface{}{
											0: id,
											1: href,
											2: reg_label.ReplaceAllString(label, "${label}"),
											3: reg_label.ReplaceAllString(label, "${num}"),
											4: text,
										})

										// if "33" != id {
										// 	return
										// }

										ctx.AddQueue(&request.Request{
											Url:  "http://car.autohome.com.cn" + href,
											Rule: "series",
											Temp: map[string]interface{}{
												"brand": id,
											},
										})
									}
								}

							})

						})
					})

				},
			},
			"series": {
				ItemFields: []string{
					"id",
					"href",
					"name",
					"sub",
					"brand",
					"sname",
					"imgurl",
					"onsale",
					"brimgurl",
				},
				ParseFunc: func(ctx *Context) {
					dom := ctx.GetDom()

					if nil != dom.Has(".price-page") {
						// logs.Log.Critical("series:")
						dom.Find(".page a").Each(func(i int, a *goquery.Selection) {
							if !a.HasClass("page-item-prev") && !a.HasClass("page-item-next") && !a.HasClass("current") {

								if href, ok := a.Attr("href"); ok {

									ctx.AddQueue(&request.Request{
										Url:  "http://car.autohome.com.cn" + href,
										Rule: "series",
										Temp: map[string]interface{}{
											"brand": ctx.GetTemp("brand", 0),
										},
									})
								}

							}
						})
					}

					sta := dom.Find(".brandtab-cont .tab-nav ul .current").Text()
					// logs.Log.Critical("sta:%v", sta)
					var onsale int
					if "停售" == sta {
						onsale = 0
					} else {
						onsale = 1
					}

					bimg, ok := dom.Find(".carbradn-pic img").Attr("src")

					if !ok {
						bimg = ``
					}

					dom.Find(".brand-title").Each(func(i int, btitle *goquery.Selection) {

						link := btitle.Find("a.link-title")
						if href, ok := link.Attr("href"); ok {
							sub := regexp.MustCompile(`\/price\/brand\-(?P<brand>\d+)\-(?P<sub>\d+)\.html`).ReplaceAllString(href, "${sub}")
							sname := link.Text()

							btitle.NextFilteredUntil(".list-cont", ".brand-title").Each(func(j int, cont *goquery.Selection) {
								mtitle := cont.Find(".main-title")
								imgurl, img := cont.Find(".list-cont-img img").Attr("src")
								if !img {
									imgurl = ""
								}

								if href, ok := mtitle.Find("a").First().Attr("href"); ok {
									id := regexp.MustCompile(`\/price\/series\-(?P<id>\d+)(\-\d+)*\.html\#pvareaid\=\d+`).ReplaceAllString(href, "${id}")
									ctx.Output(map[int]interface{}{
										0: id,
										1: href,
										2: mtitle.Text(),
										3: sub,
										4: ctx.GetTemp("brand", 0),
										5: sname,
										6: imgurl,
										7: onsale,
										8: bimg,
									})

									// ctx.AddQueue(&request.Request{
									// 	Url:  "http://car.autohome.com.cn" + href,
									// 	Rule: "spec",
									// 	Temp: map[string]interface{}{
									// 		"imgurl": imgurl,
									// 		"series": id,
									// 		"brand":  ctx.GetTemp("brand", 0),
									// 		"sub":    sub,
									// 		"onsale": onsale,
									// 	},
									// })
									// ctx.AddQueue(&request.Request{
									// 	Url:  "http://carif.api.autohome.com.cn/dealer/LoadDealerPrice.ashx?_callback=LoadDealerPrice&type=1&city=450100&seriesid=" + id,
									// 	Rule: "LoadDealerPrice",
									// 	Temp: map[string]interface{}{
									// 		"series": id,
									// 		"brand":  ctx.GetTemp("brand", 0),
									// 		"sub":    sub,
									// 		"onsale": onsale,
									// 	},
									// })
								}

							})
						}

					})
				},
			},
			"LoadDealerPrice": {
				ItemFields: []string{
					"string",
					"series",
					"brand",
					"sub",
					"onsale",
				},
				ParseFunc: func(ctx *Context) {
					str := regexp.MustCompile(`LoadDealerPrice\((?P<content>.*?)\)`).ReplaceAllString(ctx.GetText(), "${content}")
					// logs.Log.Critical("series:%v,content:%v",ctx.GetTemp("series",""),str)
					// json.Unmarshal(str)

					ctx.Output(map[int]interface{}{
						0: str,
						1: ctx.GetTemp("series", ""),
						2: ctx.GetTemp("brand", 0),
						3: ctx.GetTemp("sub", 0),
						4: ctx.GetTemp("onsale", 1),
					})
				},
			},
			"spec": {
				ItemFields: []string{
					"id",
					"name",
					"series",
					"brand",
					"sub",
					"onsale",
					"tag",
					"guidance",
				},
				ParseFunc: func(ctx *Context) {
					dom := ctx.GetDom()

					dom.Find(".interval01").Each(func(i int, div *goquery.Selection) {
						tag := div.Find(".interval01-list-cars-text").Text()

						div.Find("ul.interval01-list>li").Each(func(i int, li *goquery.Selection) {
							if id, ok := li.Attr("data-value"); ok {
								name := li.Find(".interval01-list-cars-infor>p").First().Text()
								guidance := li.Find(".interval01-list-guidance").First().Text()
								// regexp.MustCompile(``).ReplaceAllString(guidance)\s*(\d+\.\d+)万
								ctx.Output(map[int]interface{}{
									0: id,
									1: name,
									2: ctx.GetTemp("series", 0),
									3: ctx.GetTemp("brand", 0),
									4: ctx.GetTemp("sub", 0),
									5: ctx.GetTemp("onsale", 1),
									6: tag,
									7: regexp.MustCompile(`\s*(\d+\.\d+)万`).ReplaceAllString(guidance, "$1"),
								})

								ctx.AddQueue(&request.Request{
									Url:  fmt.Sprintf("http://car.autohome.com.cn/config/spec/%s.html#pvareaid=102170", id),
									Rule: "config",
									Temp: map[string]interface{}{
										"id": id,
									},
								})
							}
						})
					})

				},
			},
			"config": {
				ItemFields: []string{
					"id",
					"engine_model",
					"engine_displazement",
					"engine_displacement",
					"engine_hs",
					"body_seat",
				},
				ParseFunc: func(ctx *Context) {
					// str := ctx.GetText()

					slize := regexp.MustCompile(`\s+var\sconfig\s=\s(.*?);`).FindAllString(ctx.GetText(), -1)

					if 0 != len(slize) {

						str := regexp.MustCompile(`\s+var\sconfig\s=\s(.*?);`).ReplaceAllString(slize[0], "$1")

						vconfigz := &vconfig{}

						err := json.Unmarshal([]byte(str), &vconfigz)

						if nil != err {
							// logs.Logs.Error("err:%v",err)
							logs.Log.Error(err.Error())
						} else {
							// logs.Log.Critical("len:%d",vconfigz.Result.Specid)

							configx := &configz{}
							configx.Id = vconfigz.Result.Specid

							for _, paramtype := range vconfigz.Result.Paramtypeitems {

								if `发动机` == paramtype.Name {
									// for _,paramitem := range paramtype.Paramitems {
									// for _,valueitem := range paramitem.Valueitems{
									// 	if(vconfigz.Result.Specid == valueitem.Specid){
									// 		logs.Log.Critical("name:%s,value:%v",paramitem.Name,valueitem.Value)
									// 	}
									// }
									// }
									configx.Engine.model = __parze(paramtype.Paramitems[0].Valueitems, configx.Id)
									configx.Engine.displazement = __parze(paramtype.Paramitems[1].Valueitems, configx.Id)
									configx.Engine.displacement = __parze(paramtype.Paramitems[2].Valueitems, configx.Id)
									configx.Engine.hs = __parze(paramtype.Paramitems[11].Valueitems, configx.Id)
								} else if `车身` == paramtype.Name {
									configx.Body.seat = __parze(paramtype.Paramitems[10].Valueitems, configx.Id)
								}
							}

							ctx.Output(map[int]interface{}{
								0: configx.Id,
								1: configx.Engine.model,
								2: configx.Engine.displazement,
								3: configx.Engine.displacement,
								4: configx.Engine.hs,
								5: configx.Body.seat,
							})
						}

					}
				},
			},
		},
	},
}

func __parze(vvalueitems []vvalueitem, id int) string {
	for _, item := range vvalueitems {
		if item.Specid == id {
			return item.Value
		}
	}

	return ``
}

type body struct {
	seat string
}

type engine struct {
	model        string
	displacement string
	displazement string
	hs           string
}

type configz struct {
	Id     int
	Engine engine
	Body   body
}

type vspecitem struct {
	Showstate int
	Specid    int
	Specstate int
}

type vvalueitem struct {
	Specid int
	Value  string
}

type vparamitem struct {
	Id         int
	Name       string
	Valueitems []vvalueitem
}

type vparamtypeitem struct {
	Name       string
	Paramitems []vparamitem
}

type vresult struct {
	Paramtypeitems []vparamtypeitem
	Specid         int
	Specslist      []vspecitem
}

type vconfig struct {
	Message    string
	Result     vresult
	Returncode int
}

// http://car0.autoimg.cn/upload/2014/3/7/s_201403071839012684435.jpg
// http://car0.autoimg.cn/upload/2014/3/7/1024x0_1_q87_201403071839012684435.jpg
// http://car3.autoimg.cn/cardfs/product/g21/M12/22/C0/s_autohomecar__wKgFVVmftnqAAol-AAgZhvEyFss040.jpg
// http://car3.autoimg.cn/cardfs/product/g21/M12/22/C0/1024x0_1_q87_autohomecar__wKgFVVmftnqAAol-AAgZhvEyFss040.jpg
